package com.oa.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.oa.back.ResponseBack;
import com.oa.common.base.Page;
import com.oa.common.base.Pageable;
import com.oa.common.dto.FlowDto;
import com.oa.common.enums.CodeStatus;
import com.oa.common.eums.EntityStatus;
import com.oa.common.interfaces.PreFilter;
import com.oa.common.vo.FlowVo;
import com.oa.dao.BaseDao;
import com.oa.dao.FlowDao;
import com.oa.dao.PreFilters;
import com.oa.entities.User;
import com.oa.entities.flows.AppType;
import com.oa.entities.flows.Flow;
import com.oa.entities.flows.Form;
import com.oa.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class FlowServiceImpl extends UndeleteServiceImpl<Long,Flow> implements FlowService {

    @Autowired
    private FlowDao flowDao;

    @Autowired
    private UserService userService;

    @Autowired
    private FormService formService;

    @Autowired
    private AppsTypeService typeService;

    @Override
    protected BaseDao<Long, Flow> getSelfDao() {
        return flowDao;
    }

    @Override
    public void setClass(Class<Flow> clazz) {

    }

    @Override
    public Page<FlowVo> findPage(Pageable pageable, String key, Long typeId) {
        Page<Flow> page= flowDao.findPage(pageable,key,typeId);
        List<FlowVo> vos= new ArrayList<>();
        for (Flow flow: page.getContents()){
            vos.add(new FlowVo(flow));
        }
        return new Page<>(pageable,vos,page.getTotal());
    }

    @Override
    public List<FlowVo> find(Long typeId) {
        List<Flow> flows= flowDao.find(typeId);
        List<FlowVo> vos= new ArrayList<>();
        for (Flow flow: flows){
            vos.add(new FlowVo(flow));
        }
        return vos;
    }

    @Override
    public Flow find(Long typeId, Integer num) {
        return flowDao.find(typeId, num);
    }

    @Override
    public Boolean validate(String name, Long typeId, Long id) {
        return flowDao.validate(name, typeId, id);
    }

    @Override
    @Transactional
    public ResponseBack<String> submit(String params) {
        if (StringUtils.isEmpty(params)){
            return ResponseBack.fial(CodeStatus.PARAMS_FAIL.getResponseStatus());
        }
        FlowDto dto= JSONObject.parseObject(params,FlowDto.class);
        if (dto==null){
            return ResponseBack.fial(CodeStatus.PARAMS_FAIL.getResponseStatus());
        }
        if (StringUtils.isEmpty(dto.getName())){
            return ResponseBack.fial(CodeStatus.FLOW_NAME_NOTNULL.getResponseStatus());
        }
        if (validate(dto.getName(),dto.getTypeId(),null)){
            return ResponseBack.fial(CodeStatus.FLOW_EXIST.getResponseStatus());
        }
        AppType type=typeService.get(dto.getTypeId());
        if (type==null){
            return ResponseBack.fial(CodeStatus.FORM_UNDERFUND.getResponseStatus());
        }
        Flow flow= new Flow();
        flow.setAppType(type);
        if (dto.getFlows()!=null && dto.getFlows().length>0){
            flow.setParent(get(dto.getFlows()[0]));
        }
        flow.setAppTypeId(dto.getTypeId());
        flow.setName(dto.getName());
        flow.setAuditType(dto.getAuditType());
        flow.setDateType(dto.getDateType());
        flow.setFileType(dto.getFileType());
        flow.setFlowStatus(dto.getFlowStatus());
        flow.setNum(count(dto.getTypeId())+1);
        User user= userService.getCurrent();
        flow.setIssue(user);
        flow.setIssueId(user.getId());
        flow.setFlowUser(user);
        flow.setFlowUserId(user.getId());
        if (dto.getForms().length>0){
            List<String> forms= new LinkedList<>();
            for (Long formId: dto.getForms()){
                Form form= formService.get(formId);
                if (form!=null){
                    forms.add(form.getInputName());
                }
            }
            flow.setForms(forms);
        }
        save(flow);
        return ResponseBack.success(null);
    }

    @Override
    @Transactional
    public ResponseBack<String> disableFlow(Long id) {
        return null;
    }

    private int count(Long typeId){
        List<PreFilter> filters= new ArrayList<>();
        filters.add(PreFilters.eq(Flow.PROP_STATUS,EntityStatus.ENTITY_EABLE.getCode()));
        filters.add(PreFilters.eq(Flow.FLOW_APPS_TYPE_ID,typeId));
        PreFilter[] fs= new PreFilter[filters.size()];
        return flowDao.countByFilter(filters.toArray(fs));
    }
}
